/*
 * hlist_tpl
 * author	: calvin
 * email	: calvinwilliams@163.com
 *
 * Licensed under the LGPL v2.1, see the file LICENSE in base directory.
 */

#include "list.h"

#if defined(_WIN32)
#define int32_t		__int32
#define int64_t		__int64
#define uint32_t	unsigned __int32
#define uint64_t	unsigned __int64
#ifndef PRIi32
#define PRIi32		"%d"
#define PRIi64		"%ld"
#define PRIu32		"%u"
#define PRIu64		"%lu"
#endif
#endif

#define CREATE_HLIST_ARRAY( _this_func_ , _struct_ENV_ , _p_env_member_hlist_array_ , _p_env_member_hlist_array_size_ ) \
	int _this_func_( _struct_ENV_ *_p_env ) \
	{ \
		uint64_t		n ; \
		struct hlist_head	*p_hlist_head = NULL ; \
		\
		(_p_env)->_p_env_member_hlist_array_ = (struct hlist_head *)malloc( sizeof(struct hlist_head) * ((_p_env)->_p_env_member_hlist_array_size_) ) ; \
		if( (_p_env)->_p_env_member_hlist_array_ == NULL ) \
			return -1; \
		memset( (_p_env)->_p_env_member_hlist_array_ , 0x00 , sizeof(struct hlist_head) * ((_p_env)->_p_env_member_hlist_array_size_) ); \
		\
		for( n = 0 , p_hlist_head = (_p_env)->_p_env_member_hlist_array_ ; n < (_p_env)->_p_env_member_hlist_array_size_ ; n++ , p_hlist_head++ ) \
		{ \
			INIT_HLIST_HEAD( p_hlist_head ); \
		} \
		\
		return 0; \
	} \

typedef void funcFreeHlistNodeEntry( void *pv );

#define FREE_HLISTNODEENTRY_DIRECTLY	((void*)1)

#define DESTROY_HLIST_ARRAY( _this_func_ , _struct_ENV_ , _p_env_member_hlist_array_ , _p_env_member_hlist_array_size_ , _struct_UNIT_ , _p_unit_member_hlist_node , _free_func_ ) \
	void _this_func_( _struct_ENV_ *_p_env ) \
	{ \
		uint64_t		n ; \
		struct hlist_head	*p_hlist_head = NULL ; \
		struct hlist_node	*curr = NULL , *next = NULL ; \
		_struct_UNIT_		*p_user = NULL ; \
		\
		for( n = 0 , p_hlist_head = (_p_env)->_p_env_member_hlist_array_ ; n < (_p_env)->_p_env_member_hlist_array_size_ ; n++ , p_hlist_head++ ) \
		{ \
			hlist_for_each_safe( curr , next , p_hlist_head ) \
			{ \
				hlist_del( curr ); \
				\
				p_user = CONTAINEROF( curr , _struct_UNIT_ , _p_unit_member_hlist_node ) ; \
				if( _free_func_ == FREE_HLISTNODEENTRY_DIRECTLY ) \
					free( p_user ); \
				else \
					_free_func_( (void*)p_user ); \
			} \
		} \
		\
		free( (_p_env)->_p_env_member_hlist_array_ ); \
	} \

#define LINK_HLISTNODE_INT( _this_func_ , _struct_ENV_ , _p_env_member_hlist_array_ , _p_env_member_hlist_array_size_ , _struct_UNIT_ , _p_unit_member_hlist_node , _p_unit_member_hash_key ) \
	int _this_func_( _struct_ENV_ *_p_env , _struct_UNIT_ *_p_unit ) \
	{ \
		uint64_t		array_index ; \
		struct hlist_head	*p_hlist_head = NULL ; \
		_struct_UNIT_		*p = NULL ; \
		\
		array_index = (_p_unit)->_p_unit_member_hash_key % (_p_env)->_p_env_member_hlist_array_size_ ; \
		p_hlist_head = (_p_env)->_p_env_member_hlist_array_ + array_index ; \
		hlist_for_each_entry( p , p_hlist_head , _struct_UNIT_ , _p_unit_member_hlist_node ) \
		{ \
			if( p->_p_unit_member_hash_key == (_p_unit)->_p_unit_member_hash_key ) \
				return 1; \
		} \
		hlist_add_head( & (_p_unit->_p_unit_member_hlist_node) , p_hlist_head ); \
		\
		return 0; \
	} \

#define QUERY_HLISTNODE_INT( _this_func_ , _struct_ENV_ , _p_env_member_hlist_array_ , _p_env_member_hlist_array_size_ , _struct_UNIT_ , _p_unit_member_hlist_node , _p_unit_member_hash_key ) \
	_struct_UNIT_ *_this_func_( _struct_ENV_ *_p_env , _struct_UNIT_ *_p_unit ) \
	{ \
		uint64_t		array_index ; \
		struct hlist_head	*p_hlist_head = NULL ; \
		_struct_UNIT_		*p = NULL ; \
		\
		array_index = (_p_unit)->_p_unit_member_hash_key % (_p_env)->_p_env_member_hlist_array_size_ ; \
		p_hlist_head = (_p_env)->_p_env_member_hlist_array_ + array_index ; \
		hlist_for_each_entry( p , p_hlist_head , _struct_UNIT_ , _p_unit_member_hlist_node ) \
		{ \
			if( p->_p_unit_member_hash_key == (_p_unit)->_p_unit_member_hash_key ) \
				return p; \
		} \
		\
		return NULL; \
	} \

#define LINK_HLISTNODE_STRING( _this_func_ , _struct_ENV_ , _p_env_member_hlist_array_ , _p_env_member_hlist_array_size_ , _struct_UNIT_ , _p_unit_member_hlist_node , _p_unit_member_hash_key ) \
	int _this_func_( _struct_ENV_ *_p_env , _struct_UNIT_ *_p_unit ) \
	{ \
		uint64_t		hash_val ; \
		unsigned char		*c = NULL ; \
		uint64_t		array_index ; \
		struct hlist_head	*p_hlist_head = NULL ; \
		_struct_UNIT_		*p = NULL ; \
		\
		for( hash_val = 0 , c = (unsigned char *)((_p_unit)->_p_unit_member_hash_key) ; (*c) ; c++ ) \
			hash_val = ( (hash_val<<5) + hash_val ) + (*c) ; \
		array_index = hash_val % (_p_env)->_p_env_member_hlist_array_size_ ; \
		p_hlist_head = (_p_env)->_p_env_member_hlist_array_ + array_index ; \
		hlist_for_each_entry( p , p_hlist_head , _struct_UNIT_ , _p_unit_member_hlist_node ) \
		{ \
			if( strcmp( p->_p_unit_member_hash_key , (_p_unit)->_p_unit_member_hash_key ) == 0 ) \
				return 1; \
		} \
		hlist_add_head( & (_p_unit->_p_unit_member_hlist_node) , p_hlist_head ); \
		\
		return 0; \
	} \

#define QUERY_HLISTNODE_STRING( _this_func_ , _struct_ENV_ , _p_env_member_hlist_array_ , _p_env_member_hlist_array_size_ , _struct_UNIT_ , _p_unit_member_hlist_node , _p_unit_member_hash_key ) \
	_struct_UNIT_ *_this_func_( _struct_ENV_ *_p_env , _struct_UNIT_ *_p_unit ) \
	{ \
		uint64_t		hash_val ; \
		unsigned char		*c = NULL ; \
		uint64_t		array_index ; \
		struct hlist_head	*p_hlist_head = NULL ; \
		_struct_UNIT_		*p = NULL ; \
		\
		for( hash_val = 0 , c = (unsigned char *)((_p_unit)->_p_unit_member_hash_key) ; (*c) ; c++ ) \
			hash_val = ( (hash_val<<5) + hash_val ) + (*c) ; \
		array_index = hash_val % (_p_env)->_p_env_member_hlist_array_size_ ; \
		p_hlist_head = (_p_env)->_p_env_member_hlist_array_ + array_index ; \
		hlist_for_each_entry( p , p_hlist_head , _struct_UNIT_ , _p_unit_member_hlist_node ) \
		{ \
			if( strcmp( p->_p_unit_member_hash_key , (_p_unit)->_p_unit_member_hash_key ) == 0 ) \
				return p; \
		} \
		\
		return NULL; \
	} \

